//
//  AppDelegate.cpp
//  OpenGLDemo
//
//  Created by 石超军 on 2018/7/4.
//  Copyright © 2018年 石超军. All rights reserved.
//

#include "AppDelegateX.h"
#include <OpenGL/gl3.h>

#include <cmath>
#include "FileUtil.hpp"
#include "stb_image.h"

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#define VERTEXT_ROOT "/Users/cnscj/XcodeWorkspace/SLearnOpenGL/OpenGLDemo/VertexShader/"
#define FRAGMENT_ROOT "/Users/cnscj/XcodeWorkspace/SLearnOpenGL/OpenGLDemo/FragmentShader/"
#define TEXTURE_ROOT "/Users/cnscj/XcodeWorkspace/SLearnOpenGL/OpenGLDemo/Texture/"


void AppDelegateX::OnInit()
{
   
}
void AppDelegateX::OnRender()
{
    /* Render here */
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    
    _DarkTest2();
}

void AppDelegateX::_CoordTest1()
{
    
}

void AppDelegateX::_DarkTest2()
{
    /*顶点部分*/
    const vertexcall VCall = [](unsigned int ,unsigned int ,unsigned int ){
        float vertices[] = {
            //     ---- 位置 ----       ---- 颜色 ----     - 纹理坐标 -
            0.5f,  0.5f, 0.0f,   1.0f, 0.0f, 0.0f,   1.0f, 1.0f,   // 右上
            0.5f, -0.5f, 0.0f,   0.0f, 1.0f, 0.0f,   1.0f, 0.0f,   // 右下
            -0.5f, -0.5f, 0.0f,   0.0f, 0.0f, 1.0f,   0.0f, 0.0f,   // 左下
            -0.5f,  0.5f, 0.0f,   1.0f, 1.0f, 0.0f,   0.0f, 1.0f    // 左上
        };
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//将顶点数据写入绑定的顶点缓存对象
        
        unsigned int indices[] = {
            0, 1, 3, // first triangle
            1, 2, 3  // second triangle
        };
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
        
        // 位置属性
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
        glEnableVertexAttribArray(0);
        // 颜色属性
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3* sizeof(float)));
        glEnableVertexAttribArray(1);
        
        glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
        glEnableVertexAttribArray(2);
        
    };
    
    /* 纹理部分 */
    const texturecall TCall = [](std::function<unsigned int(const char *)> glLoadTexture){
        //纹理加载器
        unsigned int texture1 = glLoadTexture(TEXTURE_ROOT "wall.jpg");
        unsigned int texture2 = glLoadTexture(TEXTURE_ROOT "awesomeface.png");
        
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texture1);
        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, texture2);
        
    };
    
    /* 渲染的图形 */
    const rendercall DCall = [=](unsigned int ,unsigned int,unsigned int shaderProgram){
        // 译注：下面就是矩阵初始化的一个例子，如果使用的是0.9.9及以上版本
        glm::mat4 trans(1.0f);
    
        unsigned int transformLoc = glGetUniformLocation(shaderProgram, "transform");
        glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));
        
        glUniform1i(glGetUniformLocation(shaderProgram, "texture1"), 0); // 手动设置
        glUniform1i(glGetUniformLocation(shaderProgram, "texture2"), 1);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    };
    
    RenderT2( VERTEXT_ROOT "dark2.vs", FRAGMENT_ROOT "dark2.fs",&VCall, &TCall,&DCall);
}

void AppDelegateX::_DarkTest1()
{
    /*顶点部分*/
    const vertexcall VCall = [](unsigned int ,unsigned int ,unsigned int ){
        float vertices[] = {
            //     ---- 位置 ----       ---- 颜色 ----     - 纹理坐标 -
            0.5f,  0.5f, 0.0f,   1.0f, 0.0f, 0.0f,   1.0f, 1.0f,   // 右上
            0.5f, -0.5f, 0.0f,   0.0f, 1.0f, 0.0f,   1.0f, 0.0f,   // 右下
            -0.5f, -0.5f, 0.0f,   0.0f, 0.0f, 1.0f,   0.0f, 0.0f,   // 左下
            -0.5f,  0.5f, 0.0f,   1.0f, 1.0f, 0.0f,   0.0f, 1.0f    // 左上
        };
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//将顶点数据写入绑定的顶点缓存对象
        
        unsigned int indices[] = {
            0, 1, 3, // first triangle
            1, 2, 3  // second triangle
        };
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
        
        // 位置属性
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
        glEnableVertexAttribArray(0);
        // 颜色属性
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3* sizeof(float)));
        glEnableVertexAttribArray(1);
        
        glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
        glEnableVertexAttribArray(2);
        
    };
    
    /* 纹理部分 */
    const texturecall TCall = [](std::function<unsigned int(const char *)> glLoadTexture){
        //纹理加载器
        unsigned int texture1 = glLoadTexture(TEXTURE_ROOT "wall.jpg");
        
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texture1);

    };
    
    /* 渲染的图形 */
    const rendercall DCall = [=](unsigned int ,unsigned int,unsigned int shaderProgram){
        glm::mat4 trans(1.0f);
        
        unsigned int transformLoc = glGetUniformLocation(shaderProgram, "transform");
        glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));
        
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    };
    
    RenderT2( VERTEXT_ROOT "dark.vs", FRAGMENT_ROOT "dark.fs",&VCall, &TCall,&DCall);
}

void AppDelegateX::_Transform1()
{
    /*顶点部分*/
    const vertexcall VCall = [](unsigned int ,unsigned int ,unsigned int ){
        float vertices[] = {
            //     ---- 位置 ----       ---- 颜色 ----     - 纹理坐标 -
            0.5f,  0.5f, 0.0f,   1.0f, 0.0f, 0.0f,   1.0f, 1.0f,   // 右上
            0.5f, -0.5f, 0.0f,   0.0f, 1.0f, 0.0f,   1.0f, 0.0f,   // 右下
            -0.5f, -0.5f, 0.0f,   0.0f, 0.0f, 1.0f,   0.0f, 0.0f,   // 左下
            -0.5f,  0.5f, 0.0f,   1.0f, 1.0f, 0.0f,   0.0f, 1.0f    // 左上
        };
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//将顶点数据写入绑定的顶点缓存对象
        
        unsigned int indices[] = {
            0, 1, 3, // first triangle
            1, 2, 3  // second triangle
        };
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
        
        // 位置属性
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
        glEnableVertexAttribArray(0);
        // 颜色属性
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3* sizeof(float)));
        glEnableVertexAttribArray(1);
        
        glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
        glEnableVertexAttribArray(2);
        
    };
    
    /* 纹理部分 */
    const texturecall TCall = [](std::function<unsigned int(const char *)> glLoadTexture){
        //纹理加载器
        unsigned int texture1 = glLoadTexture(TEXTURE_ROOT "wall.jpg");
        unsigned int texture2 = glLoadTexture(TEXTURE_ROOT "awesomeface.png");
        
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texture1);
        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, texture2);
        
    };
    
    /* 渲染的图形 */
    const rendercall DCall = [=](unsigned int ,unsigned int,unsigned int shaderProgram){
        // 译注：下面就是矩阵初始化的一个例子，如果使用的是0.9.9及以上版本
        glm::mat4 trans(1.0f);
        
        trans = glm::rotate(trans, glm::radians(90.0f), glm::vec3(0.0, 0.0, 1.0));
        trans = glm::scale(trans, glm::vec3(0.5, 0.5, 0.5));

        unsigned int transformLoc = glGetUniformLocation(shaderProgram, "transform");
        glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));
        
        glUniform1i(glGetUniformLocation(shaderProgram, "texture1"), 0); // 手动设置
        glUniform1i(glGetUniformLocation(shaderProgram, "texture2"), 1);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    };
    
    RenderT2( VERTEXT_ROOT "transformTest1.vs", FRAGMENT_ROOT "textureTest2.fs",&VCall, &TCall,&DCall);
    
}

void AppDelegateX::_TextureTest2()
{
    /*顶点部分*/
    const vertexcall VCall = [](unsigned int ,unsigned int ,unsigned int ){
        float vertices[] = {
            //     ---- 位置 ----       ---- 颜色 ----     - 纹理坐标 -
            0.5f,  0.5f, 0.0f,   1.0f, 0.0f, 0.0f,   1.0f, 1.0f,   // 右上
            0.5f, -0.5f, 0.0f,   0.0f, 1.0f, 0.0f,   1.0f, 0.0f,   // 右下
            -0.5f, -0.5f, 0.0f,   0.0f, 0.0f, 1.0f,   0.0f, 0.0f,   // 左下
            -0.5f,  0.5f, 0.0f,   1.0f, 1.0f, 0.0f,   0.0f, 1.0f    // 左上
        };
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//将顶点数据写入绑定的顶点缓存对象
        
        unsigned int indices[] = {
            0, 1, 3, // first triangle
            1, 2, 3  // second triangle
        };
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
        
        // 位置属性
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
        glEnableVertexAttribArray(0);
        // 颜色属性
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3* sizeof(float)));
        glEnableVertexAttribArray(1);
        
        glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
        glEnableVertexAttribArray(2);
        
    };
    /* 纹理部分 */
    const texturecall TCall = [](std::function<unsigned int(const char *)> glLoadTexture){
        //纹理加载器
        unsigned int texture1 = glLoadTexture(TEXTURE_ROOT "wall.jpg");
        unsigned int texture2 = glLoadTexture(TEXTURE_ROOT "awesomeface.png");
        
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texture1);
        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, texture2);
        
    };
    
    /* 渲染的图形 */
    const rendercall DCall = [=](unsigned int ,unsigned int,unsigned int shaderProgram ){
        glUniform1i(glGetUniformLocation(shaderProgram, "texture1"), 0); // 手动设置
        glUniform1i(glGetUniformLocation(shaderProgram, "texture2"), 1);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    };
    
    RenderT2(VERTEXT_ROOT "textureTest1.vs", FRAGMENT_ROOT "textureTest2.fs",&VCall, &TCall , &DCall);
}

void AppDelegateX::_TextureTest1()
{
    /*顶点部分*/
    const vertexcall VCall = [](unsigned int ,unsigned int ,unsigned int ){
        float vertices[] = {
            //     ---- 位置 ----       ---- 颜色 ----     - 纹理坐标 -
            0.5f,  0.5f, 0.0f,   1.0f, 0.0f, 0.0f,   1.0f, 1.0f,   // 右上
            0.5f, -0.5f, 0.0f,   0.0f, 1.0f, 0.0f,   1.0f, 0.0f,   // 右下
            -0.5f, -0.5f, 0.0f,   0.0f, 0.0f, 1.0f,   0.0f, 0.0f,   // 左下
            -0.5f,  0.5f, 0.0f,   1.0f, 1.0f, 0.0f,   0.0f, 1.0f    // 左上
        };
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//将顶点数据写入绑定的顶点缓存对象
        
        unsigned int indices[] = {
            0, 1, 3, // first triangle
            1, 2, 3  // second triangle
        };
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
        
        // 位置属性
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
        glEnableVertexAttribArray(0);
        // 颜色属性
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3* sizeof(float)));
        glEnableVertexAttribArray(1);
        
        glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
        glEnableVertexAttribArray(2);
        
    };
    
    /* 渲染的图形 */
    const rendercall DCall = [=](unsigned int ,unsigned int,unsigned int ){
        
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    };
    
    RenderT(TEXTURE_ROOT "wall.jpg", VERTEXT_ROOT "textureTest1.vs", FRAGMENT_ROOT "textureTest1.fs",&VCall, &DCall);
    
}

void AppDelegateX::_ShaderTest4()
{
    /*顶点部分*/
    const vertexcall VCall = [](unsigned int,unsigned int VAO,unsigned int VBO){
        float vertices[] = {
            // 位置              // 颜色
            0.5f, -0.5f, 0.0f,  1.0f, 0.0f, 0.0f,   // 右下
            -0.5f, -0.5f, 0.0f,  0.0f, 1.0f, 0.0f,   // 左下
            0.0f,  0.5f, 0.0f,  0.0f, 0.0f, 1.0f    // 顶部
        };
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//将顶点数据写入绑定的顶点缓存对象
        
        // 位置属性
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
        glEnableVertexAttribArray(0);
        // 颜色属性
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3* sizeof(float)));
        glEnableVertexAttribArray(1);
    };
    
    /* 着色器部分 */
    std::string vertexShaderSource = FileUtil::ReadText(VERTEXT_ROOT "shaderTest4.c");
    std::string fragmentShaderSource = FileUtil::ReadText(FRAGMENT_ROOT "shaderTest4.c");
    
    /* 渲染的图形 */
    const rendercall DCall = [](unsigned int,unsigned int,unsigned int shaderProgram){
        glDrawArrays(GL_TRIANGLES, 0, 3);
    };
    
    Render(&VCall, vertexShaderSource.c_str(), fragmentShaderSource.c_str(), &DCall);
}

void AppDelegateX::_ShaderTest3()
{
    /* 顶点部分 */
    ///1-创建顶点数据
    float vertices[] = {
        -0.5f, -0.5f, 0.0f,
        0.5f, -0.5f, 0.0f,
        0.0f,  0.5f, 0.0f
    };
    
    /*顶点着色器输出作为片段着色器输入*/
    std::string vertexShaderSource = FileUtil::ReadText(VERTEXT_ROOT "default.vs");
    std::string fragmentShaderSource = FileUtil::ReadText(FRAGMENT_ROOT "shaderTest3.c");
    
    /* 渲染的图形 */
    const rendercall draw = [](unsigned int,unsigned int,unsigned int shaderProgram){
        float timeValue = glfwGetTime();
        float greenValue = (sin(timeValue) / 2.0f) + 0.5f;
        int vertexColorLocation = glGetUniformLocation(shaderProgram, "ourColor");
        glUniform4f(vertexColorLocation, 0.0f, greenValue, 0.0f, 1.0f);
        glDrawArrays(GL_TRIANGLES, 0, 3);
    };
    
    Render(vertices, sizeof(vertices), vertexShaderSource.c_str(), fragmentShaderSource.c_str(), &draw);
}

void AppDelegateX::_ShaderTest2()
{
    /* 顶点部分 */
    ///1-创建顶点数据
    float vertices[] = {
        -0.5f, -0.5f, 0.0f,
        0.5f, -0.5f, 0.0f,
        0.0f,  0.5f, 0.0f
    };
    
    /*顶点着色器输出作为片段着色器输入*/
    std::string vertexShaderSource = FileUtil::ReadText(VERTEXT_ROOT "shaderTest2.c");
    std::string fragmentShaderSource = FileUtil::ReadText(FRAGMENT_ROOT "shaderTest2.c");
    
    /* 渲染的图形 */
    const rendercall draw = [](unsigned int,unsigned int,unsigned int shaderProgram){
        glDrawArrays(GL_TRIANGLES, 0, 3);
    };
    
    Render(vertices, sizeof(vertices), vertexShaderSource.c_str(), fragmentShaderSource.c_str(), &draw);
}


void AppDelegateX::_ShaderTest1()
{
    /* 顶点部分 */
    ///1-创建顶点数据
    float vertices[] = {
        -0.5f, -0.5f, 0.0f,
        0.5f, -0.5f, 0.0f,
        0.0f,  0.5f, 0.0f
    };
    
    /*顶点着色器输出作为片段着色器输入*/
    const char *vertexShaderSource = //着色器代码
    "#version 330 core\n"
    "layout (location = 0) in vec3 aPos;\n" // 位置变量的属性位置值为0
    "out vec4 vertexColor;\n"               // *为片段着色器指定一个颜色输出
    "void main()\n"
    "{\n"
        "gl_Position = vec4(aPos, 1.0);\n"  // 注意我们如何把一个vec3作为vec4的构造器的参数
        "vertexColor = vec4(0.5, 0.0, 0.0, 1.0);\n" // 把输出变量设置为暗红色
    "}\n";
    
    const char *fragmentShaderSource =  //着色器代码
    "#version 330 core\n"
    "out vec4 FragColor;\n"
    "in vec4 vertexColor;\n"            // *从顶点着色器传来的输入变量（名称相同、类型相同）
    "void main()\n"
    "{\n"
        "FragColor = vertexColor;\n"
    "}\n";
    
    
    const rendercall draw = [](unsigned int,unsigned int,unsigned int){
        glDrawArrays(GL_TRIANGLES, 0, 3);
        
    };
    
    Render(vertices, sizeof(vertices), vertexShaderSource, fragmentShaderSource,&draw);
}

void AppDelegateX::_TriangleTest()
{
    /* 顶点部分 */
    ///1-创建顶点数据
    float vertices[] = {
        -0.5f, -0.5f, 0.0f,
        0.5f, -0.5f, 0.0f,
        0.0f,  0.5f, 0.0f
    };
    
    const char *vertexShaderSource = //着色器代码
    "#version 330 core\n"
    "layout (location = 0) in vec3 aPos;\n"
    "\n"
    "void main()\n"
    "{\n"
    "    gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
    "}\n";
    
    const char *fragmentShaderSource = //着色器代码
    "#version 330 core\n"
    "out vec4 FragColor;\n"
    "\n"
    "void main()\n"
    "{\n"
    "    FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
    "}\n";
    
    const rendercall draw = [](unsigned int,unsigned int,unsigned int){
        glDrawArrays(GL_TRIANGLES, 0, 3);
        
    };
    
    Render(vertices, sizeof(vertices), vertexShaderSource, fragmentShaderSource,&draw);
}

void AppDelegateX::_OldTriangleTest()
{
    /* 顶点部分 */
    ///1-创建顶点数据
    float vertices[] = {
        -0.5f, -0.5f, 0.0f,
        0.5f, -0.5f, 0.0f,
        0.0f,  0.5f, 0.0f
    };
    
    ///2-VBO,VAO对象设置及链接
    //注:OpenGL的核心模式要求我们使用VAO
    unsigned int VBO;//生成一个VBO(顶点缓存对象)
    glGenBuffers(1, &VBO);
    unsigned int VAO;///生成一个VAO(顶点数组对象)
    glGenVertexArrays(1, &VAO);
    
    ///3-绑定设置到VAO中,绑定VBO到缓存数组中
    glBindVertexArray(VAO);    //绑定设置到VAO-接下来的设置都会保存到VAO中
    glBindBuffer(GL_ARRAY_BUFFER, VBO);//绑定VBO对象到GL_ARRAY_BUFFER-任何（在GL_ARRAY_BUFFER目标上的）缓冲调用都会用来配置当前绑定的缓冲
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//将顶点数据写入绑定的顶点缓存对象
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);   //解释绑定的VBO中,顶点的属性-与顶点着色代码的location有关
    glEnableVertexAttribArray(0);       //启用顶点属性
    glBindBuffer(GL_ARRAY_BUFFER, 0);   //解除绑定VBO对象
    glBindVertexArray(0);       //解除绑定
    
    /* 着色器部分 */
    ///4-生成编译顶点着色器
    const char *vertexShaderSource = //着色器代码
    "#version 330 core\n"
    "layout (location = 0) in vec3 aPos;\n"
    "\n"
    "void main()\n"
    "{\n"
    "    gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
    "}\n";
    unsigned int vertexShader;
    vertexShader = glCreateShader(GL_VERTEX_SHADER); //生成着色器
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); //将着色器源代码写入着色器
    glCompileShader(vertexShader);  //编译着色器
    //Debug部分可省略
    int  successVS;
    char infoLogVS[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &successVS);
    if(!successVS)
    {
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLogVS);
        std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLogVS << std::endl;
        return;
    }
    
    ///5-生成编译片段着色器
    const char *fragmentShaderSource = //着色器代码
    "#version 330 core\n"
    "out vec4 FragColor;\n"
    "\n"
    "void main()\n"
    "{\n"
    "    FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
    "}\n";
    unsigned int fragmentShader;
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);
    //Debug部分可省略
    int  successFS;
    char infoLogFS[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &successFS);
    if(!successFS)
    {
        glGetShaderInfoLog(fragmentShader, 512, NULL, infoLogFS);
        std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLogFS << std::endl;
        return;
    }
    
    ///6-创建着色器程序,链接着色器
    unsigned int shaderProgram;
    shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);    //链接顶点着色器
    glAttachShader(shaderProgram, fragmentShader);  //链接片段着色器
    glLinkProgram(shaderProgram);   //链接着色器程序
    //Debug部分可省略
    int  successSP;
    char infoLogSP[512];
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &successSP);
    if(!successSP) {
        glGetProgramInfoLog(shaderProgram, 512, NULL, infoLogSP);
        std::cout << "ERROR::SHADERPROGRAME::COMPILATION_FAILED\n" << infoLogFS << std::endl;
        return;
    }
    glDeleteShader(vertexShader);           //移除顶点着色器
    glDeleteShader(fragmentShader);         ///移除片段着色器
    
    /* 渲染部分 */
    //7-绘制
    glUseProgram(shaderProgram);        //激活着色器程序
    glBindVertexArray(VAO);             //激活顶点数组对象
    glDrawArrays(GL_TRIANGLES, 0, 3);
    
    /* 其他 */
    //8-善后工作
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteProgram(shaderProgram);
    
}

void AppDelegateX::Render(const float vertices[],
                         unsigned int verticesLen,
                         const char *vertexSource,
                         const char *fragmentSource,
                         const rendercall *draw)
{
    /* 顶点部分 */
    ///1-创建顶点数据
    const float *vertexData = vertices;
    
    ///2-VBO,VAO对象设置及链接
    //注:OpenGL的核心模式要求我们使用VAO
    unsigned int VBO;//生成一个VBO(顶点缓存对象)
    glGenBuffers(1, &VBO);
    unsigned int VAO;///生成一个VAO(顶点数组对象)
    glGenVertexArrays(1, &VAO);
    
    ///3-绑定设置到VAO中,绑定VBO到缓存数组中
    glBindVertexArray(VAO);    //绑定设置到VAO-接下来的设置都会保存到VAO中
    glBindBuffer(GL_ARRAY_BUFFER, VBO);//绑定VBO对象到GL_ARRAY_BUFFER-任何（在GL_ARRAY_BUFFER目标上的）缓冲调用都会用来配置当前绑定的缓冲
    glBufferData(GL_ARRAY_BUFFER, verticesLen, vertexData, GL_STATIC_DRAW);//将顶点数据写入绑定的顶点缓存对象
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);   //解释绑定的VBO中,顶点的属性-与顶点着色代码的location有关
    glEnableVertexAttribArray(0);       //启用顶点属性
    glBindBuffer(GL_ARRAY_BUFFER, 0);   //解除绑定VBO对象
    glBindVertexArray(0);       //解除绑定
    
    /* 着色器部分 */
    ///4-生成编译顶点着色器
    const char *vertexShaderSource = vertexSource;//着色器代码
    unsigned int vertexShader;
    vertexShader = glCreateShader(GL_VERTEX_SHADER); //生成着色器
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); //将着色器源代码写入着色器
    glCompileShader(vertexShader);  //编译着色器
    //Debug部分可省略
    int  successVS;
    char infoLogVS[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &successVS);
    if(!successVS)
    {
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLogVS);
        std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLogVS << std::endl;
        return;
    }
    
    ///5-生成编译片段着色器
    const char *fragmentShaderSource = fragmentSource;//着色器代码
    unsigned int fragmentShader;
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);
    //Debug部分可省略
    int  successFS;
    char infoLogFS[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &successFS);
    if(!successFS)
    {
        glGetShaderInfoLog(fragmentShader, 512, NULL, infoLogFS);
        std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLogFS << std::endl;
        return;
    }
    
    ///6-创建着色器程序,链接着色器
    unsigned int shaderProgram;
    shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);    //链接顶点着色器
    glAttachShader(shaderProgram, fragmentShader);  //链接片段着色器
    glLinkProgram(shaderProgram);   //链接着色器程序
    //Debug部分可省略
    int  successSP;
    char infoLogSP[512];
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &successSP);
    if(!successSP) {
        glGetProgramInfoLog(shaderProgram, 512, NULL, infoLogSP);
        std::cout << "ERROR::SHADERPROGRAME::COMPILATION_FAILED\n" << infoLogFS << std::endl;
        return;
    }
    glDeleteShader(vertexShader);           //移除顶点着色器
    glDeleteShader(fragmentShader);         ///移除片段着色器
    
    /* 渲染部分 */
    //7-绘制-这里是必须循环
    {
        glUseProgram(shaderProgram);        //激活着色器程序
        glBindVertexArray(VAO);             //激活顶点数组对象
        (*draw)(VAO,VBO,shaderProgram);
    }
    
    /* 其他 */
    //8-善后工作
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteProgram(shaderProgram);
}

void AppDelegateX::Render(
            const vertexcall *vertexCall,
            const char *vertexSource,
            const char *fragmentSource,
            const rendercall *drawCall)
{
    /* 顶点部分 */
    ///1-创建顶点数据
    
    
    ///2-VBO,VAO对象设置及链接
    //注:OpenGL的核心模式要求我们使用VAO
    unsigned int VBO;//生成一个VBO(顶点缓存对象)
    glGenBuffers(1, &VBO);
    unsigned int VAO;///生成一个VAO(顶点数组对象)
    glGenVertexArrays(1, &VAO);
    
    ///3-绑定设置到VAO中,绑定VBO到缓存数组中
    glBindVertexArray(VAO);    //绑定设置到VAO-接下来的设置都会保存到VAO中
    glBindBuffer(GL_ARRAY_BUFFER, VBO);//绑定VBO对象到GL_ARRAY_BUFFER-任何（在GL_ARRAY_BUFFER目标上的）缓冲调用都会用来配置当前绑定的缓冲
    
    (*vertexCall)(0,VAO,VBO);
    
    glBindBuffer(GL_ARRAY_BUFFER, 0);   //解除绑定VBO对象
    glBindVertexArray(0);       //解除绑定
    
    /* 着色器部分 */
    ///4-生成编译顶点着色器
    const char *vertexShaderSource = vertexSource;//着色器代码
    unsigned int vertexShader;
    vertexShader = glCreateShader(GL_VERTEX_SHADER); //生成着色器
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); //将着色器源代码写入着色器
    glCompileShader(vertexShader);  //编译着色器
    //Debug部分可省略
    int  successVS;
    char infoLogVS[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &successVS);
    if(!successVS)
    {
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLogVS);
        std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLogVS << std::endl;
        return;
    }
    
    ///5-生成编译片段着色器
    const char *fragmentShaderSource = fragmentSource;//着色器代码
    unsigned int fragmentShader;
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);
    //Debug部分可省略
    int  successFS;
    char infoLogFS[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &successFS);
    if(!successFS)
    {
        glGetShaderInfoLog(fragmentShader, 512, NULL, infoLogFS);
        std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLogFS << std::endl;
        return;
    }
    
    ///6-创建着色器程序,链接着色器
    unsigned int shaderProgram;
    shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);    //链接顶点着色器
    glAttachShader(shaderProgram, fragmentShader);  //链接片段着色器
    glLinkProgram(shaderProgram);   //链接着色器程序
    //Debug部分可省略
    int  successSP;
    char infoLogSP[512];
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &successSP);
    if(!successSP) {
        glGetProgramInfoLog(shaderProgram, 512, NULL, infoLogSP);
        std::cout << "ERROR::SHADERPROGRAME::COMPILATION_FAILED\n" << infoLogFS << std::endl;
        return;
    }
    glDeleteShader(vertexShader);           //移除顶点着色器
    glDeleteShader(fragmentShader);         ///移除片段着色器
    
    /* 渲染部分 */
    //7-绘制-这里是必须循环
    {
        glUseProgram(shaderProgram);        //激活着色器程序
        glBindVertexArray(VAO);             //激活顶点数组对象
        (*drawCall)(VAO,VBO,shaderProgram);
    }
    
    /* 其他 */
    //8-善后工作
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteProgram(shaderProgram);
}

void AppDelegateX::RenderT(
             const char *textureFilePath,
             const char *vertexFilePath,
             const char *fragmentFilePath,
             const vertexcall *vertexCall,
             const rendercall *drawCall)
{
    /* 顶点部分 */
    ///1-VBO,VAO,EBO对象设置及链接
    //注:OpenGL的核心模式要求我们使用VAO
    unsigned int VBO;//生成一个VBO(顶点缓存对象)
    glGenBuffers(1, &VBO);
    unsigned int EBO;///生成一个VAO(顶点数组对象)
    glGenBuffers(1, &EBO);
    unsigned int VAO;///生成一个VAO(顶点数组对象)
    glGenVertexArrays(1, &VAO);

    
    ///3-绑定设置到VAO中,绑定VBO到缓存数组中
    glBindVertexArray(VAO);    //绑定设置到VAO-接下来的设置都会保存到VAO中
    glBindBuffer(GL_ARRAY_BUFFER, VBO);//绑定VBO对象到GL_ARRAY_BUFFER-任何（在GL_ARRAY_BUFFER目标上的）缓冲调用都会用来配置当前绑定的缓冲
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    
    (*vertexCall)(VAO,VBO,EBO);
    
    //XXX:不知道下面代码干嘛用的?
//    glBindBuffer(GL_ARRAY_BUFFER, 0);   //解除绑定VBO对象
//    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);   //解除绑定VBO对象
//    glBindVertexArray(0);       //解除绑定

    /* 着色器部分 */
    ///4-生成编译顶点着色器
    std::string vertexStr = FileUtil::ReadText(vertexFilePath);
    const char *vertexShaderSource = vertexStr.c_str();//着色器代码
    unsigned int vertexShader;
    vertexShader = glCreateShader(GL_VERTEX_SHADER); //生成着色器
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); //将着色器源代码写入着色器
    glCompileShader(vertexShader);  //编译着色器
    //Debug部分可省略
    int  successVS;
    char infoLogVS[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &successVS);
    if(!successVS)
    {
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLogVS);
        std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLogVS << std::endl;
        glDeleteShader(vertexShader);           //移除顶点着色器
        return;
    }
    
    ///5-生成编译片段着色器
    std::string fragmentStr = FileUtil::ReadText(fragmentFilePath);
    const char *fragmentShaderSource = fragmentStr.c_str();//着色器代码
    unsigned int fragmentShader;
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);
    //Debug部分可省略
    int  successFS;
    char infoLogFS[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &successFS);
    if(!successFS)
    {
        glGetShaderInfoLog(fragmentShader, 512, NULL, infoLogFS);
        std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLogFS << std::endl;
        glDeleteShader(fragmentShader);         ///移除片段着色器
        return;
    }
    
    ///6-创建着色器程序,链接着色器
    unsigned int shaderProgram;
    shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);    //链接顶点着色器
    glAttachShader(shaderProgram, fragmentShader);  //链接片段着色器
    glLinkProgram(shaderProgram);   //链接着色器程序
    //Debug部分可省略
    int  successSP;
    char infoLogSP[512];
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &successSP);
    if(!successSP) {
        glGetProgramInfoLog(shaderProgram, 512, NULL, infoLogSP);
        std::cout << "ERROR::SHADERPROGRAME::COMPILATION_FAILED\n" << infoLogFS << std::endl;
        glDeleteProgram(shaderProgram);
        return;
    }
    glDeleteShader(vertexShader);           //移除顶点着色器
    glDeleteShader(fragmentShader);         ///移除片段着色器
    
    /* 纹理加载部分 */
    unsigned int texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    // 为当前绑定的纹理对象设置环绕、过滤方式
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    // 加载并生成纹理
    int width, height, nrChannels;
    unsigned char *data = stbi_load(textureFilePath, &width, &height, &nrChannels, 0);
    if (data)
    {
        //判断颜色通道个数,决定不同的加载方式
        if(nrChannels == 3)
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
        else if(nrChannels == 4)
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
        else
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
        glGenerateMipmap(GL_TEXTURE_2D);
    }
    else
    {
        std::cout << "Failed to load texture" << std::endl;
        glDeleteTextures(1, &texture);
        return;
    }
    stbi_image_free(data);

    
    
    /* 渲染部分 */
    //7-绘制-这里是必须循环
    {
        glUseProgram(shaderProgram);        //激活着色器程序
        glBindVertexArray(VAO);             //激活顶点数组对象
        (*drawCall)(VAO,VBO,shaderProgram);
    }
    
    /* 其他 */
    //8-善后工作
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteBuffers(1, &EBO);
    glDeleteProgram(shaderProgram);
    glDeleteTextures(1, &texture);
}


void AppDelegateX::RenderT2(
              const char *vertexFilePath,
              const char *fragmentFilePath,
              const vertexcall *vertexCall,
              const texturecall *textureCall,
              const rendercall *drawCall)
{
    /* 顶点部分 */
    ///1-VBO,VAO,EBO对象设置及链接
    //注:OpenGL的核心模式要求我们使用VAO
    unsigned int VBO;//生成一个VBO(顶点缓存对象)
    glGenBuffers(1, &VBO);
    unsigned int EBO;///生成一个VAO(顶点数组对象)
    glGenBuffers(1, &EBO);
    unsigned int VAO;///生成一个VAO(顶点数组对象)
    glGenVertexArrays(1, &VAO);
    
    
    ///3-绑定设置到VAO中,绑定VBO到缓存数组中
    glBindVertexArray(VAO);    //绑定设置到VAO-接下来的设置都会保存到VAO中
    glBindBuffer(GL_ARRAY_BUFFER, VBO);//绑定VBO对象到GL_ARRAY_BUFFER-任何（在GL_ARRAY_BUFFER目标上的）缓冲调用都会用来配置当前绑定的缓冲
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    
    (*vertexCall)(VAO,VBO,EBO);
    
    //XXX:不知道下面代码干嘛用的?
    //    glBindBuffer(GL_ARRAY_BUFFER, 0);   //解除绑定VBO对象
    //    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);   //解除绑定VBO对象
    //    glBindVertexArray(0);       //解除绑定
    
    /* 着色器部分 */
    ///4-生成编译顶点着色器
    std::string vertexStr = FileUtil::ReadText(vertexFilePath);
    const char *vertexShaderSource = vertexStr.c_str();//着色器代码
    unsigned int vertexShader;
    vertexShader = glCreateShader(GL_VERTEX_SHADER); //生成着色器
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); //将着色器源代码写入着色器
    glCompileShader(vertexShader);  //编译着色器
    //Debug部分可省略
    int  successVS;
    char infoLogVS[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &successVS);
    if(!successVS)
    {
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLogVS);
        std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLogVS << std::endl;
        glDeleteShader(vertexShader);           //移除顶点着色器
        return;
    }
    
    ///5-生成编译片段着色器
    std::string fragmentStr = FileUtil::ReadText(fragmentFilePath);
    const char *fragmentShaderSource = fragmentStr.c_str();//着色器代码
    unsigned int fragmentShader;
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);
    //Debug部分可省略
    int  successFS;
    char infoLogFS[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &successFS);
    if(!successFS)
    {
        glGetShaderInfoLog(fragmentShader, 512, NULL, infoLogFS);
        std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLogFS << std::endl;
        glDeleteShader(fragmentShader);         ///移除片段着色器
        return;
    }
    
    ///6-创建着色器程序,链接着色器
    unsigned int shaderProgram;
    shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);    //链接顶点着色器
    glAttachShader(shaderProgram, fragmentShader);  //链接片段着色器
    glLinkProgram(shaderProgram);   //链接着色器程序
    //Debug部分可省略
    int  successSP;
    char infoLogSP[512];
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &successSP);
    if(!successSP) {
        glGetProgramInfoLog(shaderProgram, 512, NULL, infoLogSP);
        std::cout << "ERROR::SHADERPROGRAME::COMPILATION_FAILED\n" << infoLogFS << std::endl;
        glDeleteProgram(shaderProgram);
        return;
    }
    glDeleteShader(vertexShader);           //移除顶点着色器
    glDeleteShader(fragmentShader);         ///移除片段着色器
    
    /* 纹理加载部分 */
    //由于会造成内存溢出,所以应该放在着色器之后加载
    unsigned int textureArray[32] = {0};
    unsigned int textureArrayLen = 0;
    std::function<unsigned int(const char *)> glLoadTexture = [&](const char *file) -> unsigned int
    {
        glGenTextures(1, &textureArray[textureArrayLen]);
        glBindTexture(GL_TEXTURE_2D, textureArray[textureArrayLen]);
        // 为当前绑定的纹理对象设置环绕、过滤方式
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        // 加载并生成纹理
        int width, height, nrChannels;
        stbi_set_flip_vertically_on_load(true);         //正向加载
        unsigned char *data = stbi_load(file, &width, &height, &nrChannels, 0);
        if (data)
        {
            //判断颜色通道个数,决定不同的加载方式
            if(nrChannels == 3)
                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
            else if(nrChannels == 4)
                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
            else
                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
            
            glGenerateMipmap(GL_TEXTURE_2D);
        }
        else
        {
            std::cout << "Failed to load texture" << std::endl;
            glDeleteTextures(1, &textureArray[textureArrayLen]);
            return 0;
        }
        stbi_image_free(data);
        return textureArray[textureArrayLen++];
    };
    
    (*textureCall)(glLoadTexture);
    
    
    /* 渲染部分 */
    //7-绘制-这里是必须循环
    {
        glUseProgram(shaderProgram);        //激活着色器程序
        glBindVertexArray(VAO);             //激活顶点数组对象
        (*drawCall)(VAO,VBO,shaderProgram);
    }
    
    /* 其他 */
    //8-善后工作
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteBuffers(1, &EBO);
    glDeleteProgram(shaderProgram);
    
    for(int i=0;i<textureArrayLen;++i)
        glDeleteTextures(1, &textureArray[i]);
}
